package pathways;

/**
 * Title:        Pathways
 * Description:  Pure Java version of the Pathways Project.
 * Copyright:    Copyright (c) 2002
 * Company:      Ants Technologies
 * @author Veejay Sani
 * @version 1.0
 */

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Vector;

import pathways.Database.Implementation.CDBSelect;
import pathways.Database.Implementation.CDBUpdate;
import pathways.Database.Implementation.CDatabase;
import pathways.SpeciesSpace.CInstantiation;
import pathways.util.Debug.CDebug;

public class CReaction {

  public CReaction()
  {
    // non-graphical constructor
    mySubstrate = new CSubstrate("",0);
    myEnzyme = new CEnzyme("",0);
    myProduct = new CSubstrate("",0);
    connectingFrom = 0;
    connectingTo = 0;
    ID = 0;
    autoNumber = 0;
    
    coSubstrates = new Vector();
    coProducts = new Vector();
    additionalSubs = new Vector();
    additionalProds = new Vector();
    inhibitors = new Vector();
    
    // just for consistency I will set these also
    // but you shouldn't really use the graphical stuff
    // if you call this constructor
    myEnzyme.setConnectingTo(connectingTo);
    // this will map enzyme to substrate and products graphically
    myEnzyme.setPoint1(mySubstrate.getCoOrdinates().getPoint(connectingFrom));
    myEnzyme.setPoint2(myProduct.getCoOrdinates().getPoint(connectingTo));

    putReactionInSubstratesList();
    putReactionInProductsList();
  }
  
  public CReaction(CSubstrate substrate, CEnzyme enzyme, CSubstrate product,
                    int frompoint, int topoint, long reactionID)
  {
  /**
   * Constructor for non graphical usage of the class
   */
    mySubstrate = substrate;
    myEnzyme = enzyme;
    myProduct = product;
    connectingFrom = frompoint;
    connectingTo = topoint;
    ID = reactionID;
    autoNumber = 0;
    
    coSubstrates = new Vector();
    coProducts = new Vector();
    additionalSubs = new Vector();
    additionalProds = new Vector();
    inhibitors = new Vector();
    
    myEnzyme.setConnectingTo(connectingTo);
    // this will map enzyme to substrate and products graphically
    enzyme.setPoint1(mySubstrate.getCoOrdinates().getPoint(connectingFrom));
    enzyme.setPoint2(myProduct.getCoOrdinates().getPoint(connectingTo));

    putReactionInSubstratesList();
    putReactionInProductsList();
  }

  private void putReactionInSubstratesList()
  {
    CConnectionPoint p = mySubstrate.getConnectionPoint(connectingFrom);
    Vector rxns = p.getFirstReactionAtEachBranch();
    rxns.add(this);
    p.attachBranch(rxns.size()-1);
  }

  private void putReactionInProductsList()
  {
    CConnectionPoint p = myProduct.getConnectionPoint(connectingTo);
    Vector rxns = p.getReactionsLeadingToMe();
    rxns.add(this);
  }
  
  public CSubstrate getSubstrate()
  {
    return mySubstrate;
  }

  public CEnzyme getEnzyme()
  {
    return myEnzyme;
  }

  public CSubstrate getProduct()
  {
    return myProduct;
  }

  public int getFromPoint()
  {
    return connectingFrom;
  }

  public int getToPoint()
  {
    return connectingTo;
  }

  public void setVisibility(boolean visibility)
  {
    myEnzyme.setVisible(visibility);
    myProduct.setVisible(visibility);
    
    if (subAsEnzyme != null)
    {
       // this is a substrateAsEnzyme reaction
       // so make the arrow invisible/visible
       // and make the substrate invisible/visible
       mySubstrate.setVisible(visibility);
       subAsEnzyme.setVisible(visibility);
    }
    // finds all reactions that lead to the product and 
    // if making invisible
    //    set the visibility of the enzyme to false
    // else
    //    copy the visibility of the substrate to the enzyme
    CConnectionPoint p = null;
    Vector reactions = null;
    CReaction rxn = null;
    CSubstrate lsub = null;
    CEnzyme lenzyme = null;
    CConnectionPoint point = null;
    
    for (int i = 0; i<4; i++)
    {
      p = myProduct.getConnectionPoint(i);
      
      reactions = p.getReactionsLeadingToMe();
      
      for (int j = 0; j < reactions.size(); j++)
      {
        rxn = (CReaction)reactions.get(j);
        lsub = rxn.getSubstrate();
        lenzyme = rxn.getEnzyme();
        point = lsub.getConnectionPoint(rxn.connectingFrom);
        
        if (visibility)
        {
          if (lsub.isVisible())
          {
            if (point.isAnyBranchAttached())
            {
              // keep the enzyme invisible and do not do anything else
              //rxn.getEnzyme().setVisible(false); 
            }
            else
            {
              // make enzyme visible and attach it to the point
              rxn.getEnzyme().setVisible(true);
              
              point.rawSetAttachedBranch(rxn);
            }
          }
          else
          {
            lenzyme.setVisible(false);
          }
        }
        else
        {
          lenzyme.setVisible(false);
          // if this reaction is attached then detach it otherwise no problem
          if (point.getBranchNumForHeadReaction(rxn) == point.getAttachedBranch())
             point.rawDetachAll();
        }      
      }
    }
  }
  
  public long getID()
  {
    return ID; 
  }
  
  public void setProduct(CSubstrate prod)
  {
    myProduct = prod;
    myEnzyme.setPoint2(myProduct.getCoOrdinates().getPoint(connectingTo));
    putReactionInProductsList();
    
    // make sure that the visibility of this product is the same as the enzyme
    myProduct.setVisible(myEnzyme.isVisible());   
  }
  
  public Vector getCoSubstrates()
  {
    return coSubstrates;  
  }
  
  public Vector getCoProducts()
  {
    return coProducts;  
  }
  
  public boolean read(long rxnID, CDatabase db)
  {
    if (!readAlready)
    {
      readAlready = read2(rxnID,db); 
    }
    
    return readAlready;
  }
  
  private boolean read2(long rxnID, CDatabase db)
  {
    CDBSelect select = db.getSelect();
    
    ResultSet r = select.getReaction(rxnID);
    long subID = 0;
    long enzymeID = 0;
    long prodID = 0;
    CCompound compound = null;
    
    try{
       if (!r.next())
       {
          CDebug.println(this,"Read of ReactionID = " + rxnID + " yielded no records.");
          return false;
       }
       
       ID = rxnID;
       
       subID = r.getLong(2);
       
       // this makes sure that if 
       // a substrate is already put in the reaction
       // then that remains the substrate
       // and any other substrate will become a coSubstrate
       if (mySubstrate.getID() > 0)
       {
          if (subID != mySubstrate.getID())
          {
            // cosubstrate
            compound = new CCompound("",0);
            compound.read(subID,db);
            additionalSubs.add(new CCoCompound(compound,CCoCompound.NORMAL));
          }
	  else
	  {
	    oldSubID = subID;
	  } 
       }
       else
       {
          // read the substrate
          mySubstrate.read(subID,db);
          oldSubID = subID;
       }
       
       oldEnzymeID = enzymeID = r.getLong(3);
       prodID = r.getLong(4);
       autoNumber = r.getLong(5);
       
       myEnzyme.read(enzymeID,db);
       
       if (myProduct.getID() > 0)
       {
          if (prodID != myProduct.getID())
          {
            // coproduct
            compound = new CCompound("",0);
            compound.read(prodID,db);
            additionalProds.add(new CCoCompound(compound,CCoCompound.NORMAL));
          } 
	  else
	  {
	    oldProdID = prodID;
	  }
       }
       else
       {
          // read the product
          myProduct.read(prodID,db);
          oldProdID = prodID;
       }
       
    } catch (SQLException e) {
      ID = 0;
      oldSubID = 0;
      oldEnzymeID = 0;
      oldProdID = 0;
      CDebug.println(this,"read() Error:" + e.toString());
      return false;
    }
    
    // read additional subs and prods
    try {
      while (r.next())
      {
        subID = r.getLong(2);
        prodID = r.getLong(4);
        
        if (subID != mySubstrate.getID())
        {
          compound = new CCompound("",0);
          compound.read(subID,db);
          additionalSubs.add(new CCoCompound(compound,CCoCompound.NORMAL));
        }
        
        if (prodID != myProduct.getID())
        {
          compound = new CCompound("",0);
          compound.read(prodID,db);
          additionalProds.add(new CCoCompound(compound,CCoCompound.NORMAL));
        }
      }
    } catch(SQLException exception) {
      CDebug.println(this, "read() Unable to read additional subs & prods. Exception: " + exception.toString());
      return false; 
    }
    
    if (!readCoSubstrates(rxnID,select))
       return false;
    
    if (!readCoProducts(rxnID,select))
       return false;
    
    if (!readInhibitors(rxnID,select))
      return false;
    
    return true;
  }
  
  private boolean readCoSubstrates(long rxnID, CDBSelect select)
  {
    ResultSet r = select.getCoSubstrates2(rxnID);
    
    CCompound cmpd = null;
    long cmpdID = 0;
    String cmpdName = "";
    
    try{
      while(r.next())
      {
      
        cmpdID = r.getLong(1);
        cmpdName = r.getString(2);
        
        cmpd = new CCompound(cmpdName,cmpdID);
        
        coSubstrates.add(new CCoCompound(cmpd,CCoCompound.NORMAL));
      }
      
      r.close();
    } catch(SQLException e) {
      CDebug.println(this,"readCoSubstrates() Error when reading coSubstrates. Exception: " + e.toString());
      return false;
    } 
    
    return true;    
  }
  
  private boolean readCoProducts(long rxnID, CDBSelect select)
  {
    ResultSet r = select.getCoProducts2(rxnID);
    
    CCompound cmpd = null;
    long cmpdID = 0;
    String cmpdName = "";
    
    try{
      while(r.next())
      {
        cmpdID = r.getLong(1);
        cmpdName = r.getString(2);
        
        cmpd = new CCompound(cmpdName,cmpdID);
        
        coProducts.add(new CCoCompound(cmpd,CCoCompound.NORMAL));      
      }
      
      r.close(); 
      
    } catch(SQLException e) {
       CDebug.println(this,"readCoProducts() Error when reading coProducts. Exception: " + e.toString());
       return false;
    }
    
    return true;
  }
  
  private boolean readInhibitors(long rxnID, CDBSelect select)
  {
    ResultSet r = select.getInhibitors((int)rxnID);
    
    CCompound cmpd = null;
    long cmpdID = 0;
    String cmpdName = "";
    
    try{
      while(r.next())
      {
        cmpdID = r.getLong(1);
        cmpdName = r.getString(2);
        
        cmpd = new CCompound(cmpdName,cmpdID);
        
        inhibitors.add(new CCoCompound(cmpd,CCoCompound.NORMAL));      
      }
      
      r.close(); 
      
    } catch(SQLException e) {
       CDebug.println(this,"readInhibitors() Error occurred when reading Inhibitors. Exception: " + e.toString());
       return false;
    }
    
    return true;
  }
  
  public boolean save(CDatabase db)
  {
    CDBUpdate update = db.getUpdate();
    
    /*
    if (!mySubstrate.save(db))
    {
        CDebug.println(this,"save() Substrate did not save - Name: " + mySubstrate.getName());
        return false; 
    }
    
    if (!myEnzyme.save(db))
    {
        CDebug.println(this,"save() Enzyme did not save - Name: " + myEnzyme.getName());
        return false; 
    }
    
    if (!myProduct.save(db))
    {
        CDebug.println(this,"save() Product did not save - Name: " + myProduct.getName());
        return false; 
    }
    */
    
    if (ID > 0)
    {  
      /*if (!update.UpdateReaction(autoNumber,mySubstrate.getID(),myEnzyme.getID(),myProduct.getID()))
      {
        CDebug.println(this,"save() Unable to update the reaction - ID: " + ID);
        return false; 
      }*/
      
      if (oldSubID != mySubstrate.getID())
      {
        if (!update.UpdateSubForReaction(ID,mySubstrate.getID(),oldSubID))
        {
          CDebug.println(this,"save() Unable to update the substrate for reaction - RxnID: " + ID);
          return false; 
        }
        else
        {
          oldSubID = mySubstrate.getID();
        }
      }
      
      if (oldEnzymeID != myEnzyme.getID())
      {
        if (!update.UpdateEnzymeForReaction(ID,myEnzyme.getID()))
        {
          CDebug.println(this,"save() Unable to update the enzyme for the reaction - RxnID: " + ID);
          return false; 
        }  
        else
        {
          oldEnzymeID = myEnzyme.getID();  
        }
      }  
      
      if (oldProdID != myProduct.getID())
      {
        if (!update.UpdateProdForReaction(ID,myProduct.getID(),oldProdID))
        {
          CDebug.println(this,"save() Unable to update the product for reaction - RxnID: " + ID);
          return false; 
        }  
        else
        {
          oldProdID = myProduct.getID();  
        }
      }    
    }
    else
    {
      ID = update.newReaction(mySubstrate.getID(),myEnzyme.getID(),myProduct.getID());
      
      if (!(ID > 0))
      {
        CDebug.println(this,"save() Unable to add new reaction.");
        return false; 
      }
      else
      {
        autoNumber = db.getSelect().getAutoNumber(ID,mySubstrate.getID(),myEnzyme.getID(),myProduct.getID());
        oldSubID = mySubstrate.getID();
        oldEnzymeID = myEnzyme.getID();
        oldProdID = myProduct.getID();
      }      
    }
    
    // save additional substrates
    if (!saveAdditionalSubs(db))
    {
      CDebug.println(this,"save() Unable to saveAdditionalSubs.");
      return false; 
    }
    
    // save additional products
    if (!saveAdditionalProds(db))
    {
      CDebug.println(this,"save() Unable to saveAdditionalProds.");
      return false; 
    }
    
    // save the coSubstrates
    if (!saveCoSubstrates(db))
    {
      CDebug.println(this,"save() Unable to saveCoSubstrates.");
      return false; 
    }
    
    // save the coProducts
    if (!saveCoProducts(db))
    {
      CDebug.println(this,"save() Unable to saveCoSubstrates.");
      return false; 
    }
    
    if (!saveInhibitors(db))
    {
      CDebug.println(this,"save() Unable to saveInhibitors.");
      return false; 
    }
    
    updateStates();
    
    return true;
  }
  
  private boolean saveAdditionalSubs(CDatabase db)
  {
    CCoCompound coCmpd;
    CDBUpdate update = db.getUpdate();
    
    for(int i = 0; i < additionalSubs.size(); i++)
    {
      coCmpd = (CCoCompound)additionalSubs.get(i);
      
      if (coCmpd.getState() == CCoCompound.NEW)
      {
        if (!update.newReaction(coCmpd.getCompound().getID(),myEnzyme.getID(), myProduct.getID(),ID))
        {
          CDebug.println(this, "saveAdditionalSubs() Unable to addnew reaction for the AdditionalSubstrate: " + coCmpd.getCompound().getName());
          return false;         
        }
      }
      else if(coCmpd.getState() == CCoCompound.DELETE)
      {
        if (!update.deleteReaction(ID,coCmpd.getCompound().getID(),myProduct.getID()))
        {
          CDebug.println(this, "saveAdditionalSubs() Unable to delete reaction for the AdditionalSubstrate: " + coCmpd.getCompound().getName());
          return false;         
        }
      }   
    }  
    
    return true;
  }
  
  private boolean saveAdditionalProds(CDatabase db)
  {
    CCoCompound coCmpd;
    CDBUpdate update = db.getUpdate();
    
    for(int i = 0; i < additionalProds.size(); i++)
    {
      coCmpd = (CCoCompound)additionalProds.get(i);
      
      if (coCmpd.getState() == CCoCompound.NEW)
      {
        if (!update.newReaction(mySubstrate.getID(), myEnzyme.getID(), coCmpd.getCompound().getID(), ID))
        {
          CDebug.println(this, "saveAdditionalProds() Unable to addnew reaction for the AdditionalProduct: " + coCmpd.getCompound().getName());
          return false;         
        }
      }
      else if(coCmpd.getState() == CCoCompound.DELETE)
      {
        if (!update.deleteReaction(ID,mySubstrate.getID(),coCmpd.getCompound().getID()))
        {
          CDebug.println(this, "saveAdditionalProds() Unable to delete reaction for the AdditionalProduct: " + coCmpd.getCompound().getName());
          return false;         
        }
      }   
    }  
    
    return true;
  }

  private boolean saveInhibitors(CDatabase db)
  {
    CCoCompound coCmpd;
    CDBUpdate update = db.getUpdate();
    
    for(int i = 0; i < inhibitors.size(); i++)
    {
      coCmpd = (CCoCompound)inhibitors.get(i);
      
      if (coCmpd.getState() == CCoCompound.NEW)
      {
	int id = update.newInhibitor(coCmpd.getCompound().getName(),(int)ID);
	 
        if (id <= 0)
        {
          CDebug.println(this, "saveInhibitors() Unable to addnew Inhibitor: " + coCmpd.getCompound().getName());
          return false;         
        }
	else
	{
	  coCmpd.getCompound().setID(id);
	}
      }
      //else if(coCmpd.getState() == CCoCompound.EDIT)
      //{
	//update.updateInhibitor()
      //}
      else if(coCmpd.getState() == CCoCompound.DELETE)
      {
        if (!update.deleteInhibitor((int)coCmpd.getCompound().getID()))
        {
          CDebug.println(this, "saveInhibitors() Unable to delete Inhibitor: " + coCmpd.getCompound().getName());
          return false;         
        }
      }   
    }  
    
    return true;
  }
  
  private boolean saveCoSubstrates(CDatabase db)
  {
    CCoCompound coCmpd;
    CDBUpdate update = db.getUpdate();
    
    for(int i = 0; i < coSubstrates.size(); i++)
    {
      coCmpd = (CCoCompound)coSubstrates.get(i);
      
      if (coCmpd.getState() == CCoCompound.NEW)
      {
        if (!(update.addCoSubstrate(ID,coCmpd.getCompound().getID(),coCmpd.getParts())))
        {
          CDebug.println(this, "saveCoSubstrate() Unable to addnew coSubstrate: " + coCmpd.getCompound().getName());
          return false;         
        }
      }
      else if(coCmpd.getState() == CCoCompound.DELETE)
      {
        if (!(update.removeCoSubstrate(ID,coCmpd.getCompound().getID())))
        {
          CDebug.println(this, "saveCoSubstrate() Unable to remove coSubstrate: " + coCmpd.getCompound().getName());
          return false;         
        }
      }   
    }  
    
    return true;
  }
  
  private boolean saveCoProducts(CDatabase db)
  {
    CCoCompound coCmpd;
    CDBUpdate update = db.getUpdate();
    
    for(int i = 0; i < coProducts.size(); i++)
    {
      coCmpd = (CCoCompound)coProducts.get(i);
      
      if (coCmpd.getState() == CCoCompound.NEW)
      {
        if (!update.addCoProduct(ID,coCmpd.getCompound().getID(),coCmpd.getParts()))
        {
          CDebug.println(this, "saveCoProducts() Unable to addnew coProduct: " + coCmpd.getCompound().getName());
          return false;         
        }
      }
      else if(coCmpd.getState() == CCoCompound.DELETE)
      {
        if (!update.removeCoProduct(ID,coCmpd.getCompound().getID()))
        {
          CDebug.println(this, "saveCoProducts() Unable to remove coProduct: " + coCmpd.getCompound().getName());
          return false;         
        }
      }   
    }  
    
    return true;
  }
  
  public Vector getAdditionalSubs()
  {
    return additionalSubs;  
  }
  
  public Vector getAdditionalProds()
  {
    return additionalProds;  
  }
  
  public void addAdditionalSub(CCoCompound cmpd)
  {
    addToList(cmpd,additionalSubs);
  }
  
  public void addAdditionalProd(CCoCompound cmpd)
  {
    addToList(cmpd,additionalProds);
  }
  
  public void addCoSubstrate(CCoCompound cmpd)
  {
    addToList(cmpd,coSubstrates);
  }
  
  public void addCoProduct(CCoCompound cmpd)
  {
    addToList(cmpd,coProducts);
  }

  public void addInhibitor(CCoCompound cmpd)
  {
    addToList(cmpd,inhibitors);
  }
  
  public void removeAdditionalSub(CCoCompound cmpd)
  {
    removeFromList(cmpd,additionalSubs); 
  }
  
  public void removeAdditionalProd(CCoCompound cmpd)
  {
    removeFromList(cmpd,additionalProds); 
  }
  
  public void removeCoSubstrate(CCoCompound cmpd)
  {
    removeFromList(cmpd,coSubstrates); 
  }
  
  public void removeCoProduct(CCoCompound cmpd)
  {
    removeFromList(cmpd,coProducts); 
  }

  public void removeInhibitor(CCoCompound cmpd)
  {
    removeFromList(cmpd,inhibitors); 
  }
  
  private void addToList(CCoCompound cmpd, Vector v)
  {
    CCoCompound c = getCoCompoundFromList(cmpd,v);
    
    if (c == null)
    {
      cmpd.setState(CCoCompound.NEW);
      v.add(cmpd); 
    }
    else
    {
      if (c.getState() == CCoCompound.DELETE)
      {
        c.setState(CCoCompound.NORMAL); 
      }
    }
  }
  
  private void removeFromList(CCoCompound cmpd, Vector v)
  {
    CCoCompound c = getCoCompoundFromList(cmpd,v);
    
    if (c != null)
    {
      if (c.getState() ==  CCoCompound.NEW)
      {
        v.removeElement(c);
      }
      else if (c.getState() == CCoCompound.NORMAL)
      {
        c.setState(CCoCompound.DELETE); 
      }
    }
  }
   
  public CCoCompound getCoCompoundFromList(CCoCompound cmpd, Vector v)
  {
    CCoCompound c = null;
    
    for (int i = 0; i < v.size(); i++)
    {
      c = (CCoCompound)v.get(i);
      
      if (c.getCompound().getID() == cmpd.getCompound().getID())
      {
        return c;
      }   
    }  
    
    return null;
  }
 
  private Vector getVisiblePartOfList(Vector v)
  {
    Vector visiblePart = new Vector();
    CCoCompound cmpd = null;
    
    for (int i = 0; i<v.size();i++)
    {
      cmpd = (CCoCompound)v.get(i);
      
      if (cmpd.getState() != CCoCompound.DELETE)
      {
        visiblePart.add(cmpd); 
      }  
    }
    
    return visiblePart;
  }
  
  public Vector getVisibleAdditionalSubs()
  {
    return getVisiblePartOfList(additionalSubs);
  }
  
  public Vector getVisibleAdditionalProds()
  {
    return getVisiblePartOfList(additionalProds);
  }
  
  public Vector getVisibleCoSubstrates()
  {
    return getVisiblePartOfList(coSubstrates);
  }
  
  public Vector getVisibleCoProducts()
  {
    return getVisiblePartOfList(coProducts);
  }

  public Vector getVisibleInhibitors()
  {
    return getVisiblePartOfList(inhibitors);
  }
  
  public void rawSetSubstrate(CSubstrate s)
  {
    mySubstrate = s;  
  }
  
  public void rawSetEnzyme(CEnzyme e)
  {
    myEnzyme = e;  
  }
  
  public void rawSetProduct(CSubstrate p)
  {
    myProduct = p;
  }

  public Vector getSubstratesWithFile() {    
    Vector subs = new Vector();
    CCompound c = (CCompound)mySubstrate;
    CCoCompound temp = null;
    
    if (c.getFile() != null)
      subs.add(c);
    
    for (int i = 0; i < additionalSubs.size(); i++)
    {
      temp = (CCoCompound)additionalSubs.get(i);
      c = temp.getCompound();
      
      if (c.getFile() != null)
         subs.add(c);
    }
    
    for (int i = 0; i < coSubstrates.size(); i++)
    {
      temp = (CCoCompound)coSubstrates.get(i);
      c = temp.getCompound();
      
      if (c.getFile() != null)
         subs.add(c);
    }
    
    return subs;
  }

  public Vector getAllSubstrates() 
  {    
    Vector subs = new Vector();
    CCompound c = (CCompound)mySubstrate;
    CCoCompound temp = null;
    
    subs.add(c);
    
    for (int i = 0; i < additionalSubs.size(); i++)
    {
      temp = (CCoCompound)additionalSubs.get(i);
      c = temp.getCompound();

      subs.add(c);
    }
    
    for (int i = 0; i < coSubstrates.size(); i++)
    {
      temp = (CCoCompound)coSubstrates.get(i);
      c = temp.getCompound();
      
      subs.add(c);
    }
    
    return subs;
  }
  
  public Vector getProductsWithFile() {
    Vector prods = new Vector();
    CCompound c = (CCompound)myProduct;
    CCoCompound temp = null;
    
    if (c.getFile() != null)
      prods.add(c);
    
    for (int i = 0; i < additionalProds.size(); i++)
    {
      temp = (CCoCompound)additionalProds.get(i);
      c = temp.getCompound();
      
      if (c.getFile() != null)
         prods.add(c);
    }
    
    for (int i = 0; i < coProducts.size(); i++)
    {
      temp = (CCoCompound)coProducts.get(i);
      c = temp.getCompound();
      
      if (c.getFile() != null)
         prods.add(c);
    }
    
    return prods;
  }
  
  public Vector getAllProducts() 
  {
    Vector prods = new Vector();
    CCompound c = (CCompound)myProduct;
    CCoCompound temp = null;
    
    prods.add(c);
    
    for (int i = 0; i < additionalProds.size(); i++)
    {
      temp = (CCoCompound)additionalProds.get(i);
      c = temp.getCompound();
      
      prods.add(c);
    }
    
    for (int i = 0; i < coProducts.size(); i++)
    {
      temp = (CCoCompound)coProducts.get(i);
      c = temp.getCompound();
      
      prods.add(c);
    }
    
    return prods;
  }
  
  private void updateStates()
  {
    updateStates(additionalSubs);
    updateStates(additionalProds);
    updateStates(coSubstrates);
    updateStates(coProducts);
    updateStates(inhibitors);
  }
  
  private void updateStates(Vector v)
  {
    CCoCompound coCmpd;
    Vector deleteItems = new Vector();
    
    for(int i = 0; i < v.size(); i++)
    {
      coCmpd = (CCoCompound)v.get(i);
      
      if (coCmpd.getState() == CCoCompound.NEW)
      {
        coCmpd.setState(CCoCompound.NORMAL);
      }
      else if(coCmpd.getState() == CCoCompound.DELETE)
      {
        deleteItems.add(new Integer(i));
      }   
    }
    
    Integer integer = null;
    
    for(int i = deleteItems.size()-1; i >= 0; i--)
    {
      integer = (Integer)deleteItems.get(i);
      
      v.remove(integer.intValue());  
    }
  }
  
  public void setInstantiation(CInstantiation inst)
  {
    this.instantiation = inst;  
  }
  
  public CInstantiation getInstantiation()
  {
    return this.instantiation; 
  }
  
  public int getInstantiationID()
  {
    return (instantiation == null ? 0 : instantiation.getID());  
  }
  
  public CSubstrateAsEnzyme getSubAsEnzyme()
  {
    return subAsEnzyme;  
  }
  
  public void setSubAsEnzyme(CSubstrateAsEnzyme se)
  {
    subAsEnzyme = se;  
  }
  
  public Vector getInhibitors()
  {
    return inhibitors;  
  }
   
  private CSubstrate mySubstrate;
  private CEnzyme myEnzyme;
  private CSubstrate myProduct;
  // drawing stuff
  private int connectingFrom;
  private int connectingTo;
  private long ID;
  private Vector coSubstrates;
  private Vector coProducts;
  
  private Vector additionalSubs;
  private Vector additionalProds;
  private long autoNumber;
  
  private long oldSubID;
  private long oldProdID;
  private long oldEnzymeID;
  
  private CInstantiation instantiation;
  private boolean readAlready;
  
  private CSubstrateAsEnzyme subAsEnzyme;
  private Vector inhibitors;
}